import UIControl from "../basic/interfaces/UIControl";
import App from "../core/App";
import UIComponent from "../basic/models/UIComponent";
import UIIcon from "./UIIcon";
import UITabContent from "./UITabContent";
import * as Types from "../../types";
import * as Enums from "../basic/enums";
import * as ElementHelper from "../utils/ElementHelper";
import * as CastHelper from "../utils/CastHelper";
import * as TypeHelper from "../utils/TypeHelper";
import * as ExceptionHelper from "../utils/ExceptionHelper";

export default class UITabItem extends UIComponent implements UIControl {
    public readonly elementId: string;

    public id: string;
    public title: string;
    public url: string;
    public icon: string | false = "tab";
    public useSubTitle: boolean = false;
    public closable: boolean = true;
    public height: number = 37;
    public minWidth: number = 40;
    public maxWidth: number = 180;

    private _content: UITabContent | null = null;
    get content() {
        return this._content;
    }
    set content(value: UITabContent | null) {
        this._content = value;
    }

    private _element: HTMLElement | null = null;
    get element() {
        return document.getElementById(this.elementId);
    }

    constructor(app: App, options: Types.TabItemOption) {
        super(app);

        if (!TypeHelper.isStringWithNotEmpty(options.id)) ExceptionHelper.assertId();
        this.id = options.id;

        if (!TypeHelper.isStringWithNotEmpty(options.title)) ExceptionHelper.assertTitle();
        this.title = options.title;

        if (!TypeHelper.isStringWithNotEmpty(options.url)) ExceptionHelper.assertUrl();
        this.url = options.url;

        this.elementId = `${this.app.prefix + Enums.ComponentType.TAB_ITEM}-${this.id}`;

        this.icon = CastHelper.typeOrBooleanCast(options.icon, this.icon);
        this.useSubTitle = CastHelper.booleanCast(options.useSubTitle, this.useSubTitle);
        this.closable = CastHelper.booleanCast(options.closable, this.closable);

        this.height = Math.min(CastHelper.numberCast(options.height, this.height), this.height);
        this.maxWidth = Math.min(CastHelper.numberCast(options.maxWidth, this.maxWidth), this.maxWidth);
        this.minWidth = Math.max(CastHelper.numberCast(options.minWidth, this.minWidth), this.minWidth);
    }

    present(): DocumentFragment {
        const fragment = ElementHelper.createFragment();

        const tabItemElement = ElementHelper.createElement("div");
        tabItemElement.id = this.elementId;
        tabItemElement.setAttribute("data-tab-id", this.id);

        ElementHelper.addClasses(tabItemElement, this.app.prefix,
            Enums.ComponentType.TAB_ITEM,
            "flexbox",
            "flex-row",
            "flex-vertical-center"
        );

        ElementHelper.addStyles(tabItemElement, <Types.CSSStyleObject>{
            height: `${this.height}px`,
            maxWidth: `${this.maxWidth}px`,
            minWidth: `${this.minWidth}px`
        });

        tabItemElement.addEventListener("mousedown", (ev: MouseEvent) => {
            this.switch();
        }, true);

        this.createIcon(tabItemElement);
        this.createLabel(tabItemElement);
        this.createCloseIcon(tabItemElement);

        fragment.appendChild(tabItemElement);

        return fragment;
    }

    private createIcon(tabItemElement: HTMLElement) {
        if (this.icon === false) return;

        const tabItemIconElement = ElementHelper.createElement("div");
        ElementHelper.addClasses(tabItemIconElement, this.app.prefix,
            `${Enums.ComponentType.TAB_ITEM}-icon`,
            "flexbox",
            "flex-center"
        );

        const icon = new UIIcon(this.app, this.icon);
        const iconElement = icon.present();

        tabItemIconElement.appendChild(iconElement);
        tabItemElement.appendChild(tabItemIconElement);
    }

    private createLabel(tabItemElement: HTMLElement) {
        const tabItemLabelElement = ElementHelper.createElement("div");
        ElementHelper.addClasses(tabItemLabelElement, this.app.prefix,
            `${Enums.ComponentType.TAB_ITEM}-label`
        );
        tabItemLabelElement.innerText = this.title;
        tabItemElement.appendChild(tabItemLabelElement);
    }

    private createCloseIcon(tabItemElement: HTMLElement) {
        if (this.closable === false) return;

        const tabItemCloseElement = ElementHelper.createElement("div");
        ElementHelper.addClasses(tabItemCloseElement, this.app.prefix,
            `${Enums.ComponentType.TAB_ITEM}-close`,
            "flexbox",
            "flex-center"
        );

        tabItemCloseElement.addEventListener("mousedown", (ev: MouseEvent) => {
            ElementHelper.removeElement(this.element);
            ElementHelper.removeElement(this.content!.element);

            const index = this.app.items.indexOf(this);
            this.app.items.splice(index, 1);
            this.app.item = null;

            if (this.app.lastItem) this.app.lastItem.switch();
            else {
                const nextItem = this.app.items[this.app.items.length - 1];
                if (nextItem) nextItem.switch();
            }
        }, true);

        const icon = new UIIcon(this.app, "destroy");
        const iconElement = icon.present();

        tabItemCloseElement.appendChild(iconElement);
        tabItemElement.appendChild(tabItemCloseElement);
    }

    public switch(): void {
        if (this === this.app.item) return;

        this.app.lastItem = this.app.item;
        this.app.item = this;

        if (this.app.lastItem && this.app.lastItem.content && this.app.lastItem.content.element) {
            ElementHelper.removeClasses(this.app.lastItem.element, this.app.prefix,
                `${Enums.ComponentType.TAB_ITEM}-active`
            );

            ElementHelper.removeClasses(this.app.lastItem.content.element, this.app.prefix,
                `${Enums.ComponentType.TAB_CONTENT}-active`
            );
        }

        ElementHelper.addClasses(this.element, this.app.prefix,
            `${Enums.ComponentType.TAB_ITEM}-active`
        );

        ElementHelper.addClasses(this.content!.element, this.app.prefix,
            `${Enums.ComponentType.TAB_CONTENT}-active`
        );

        this.updateOffset();
    }

    public updateOffset(): number {
        let left = 0;
        if (this.app.items && this.app.items.length > 0) {
            const itemElemnet = this.app.items[this.app.items.length - 1].element;
            left = itemElemnet!.offsetLeft + itemElemnet!.offsetWidth;
        }
        return left;
    }

    public updateTitle(title: string): void {
        const element = this.element;
        if (!element) return;

        const titleElement = element.querySelector<HTMLElement>(`.${this.app.prefix}tab-item-label`);
        if (!titleElement) return;
        titleElement.innerText = title;
        titleElement.setAttribute("title", title);

        this.title = title;
    }
}